import {useCallback, useEffect, useState} from 'react';
import {usePayment} from '../../../hooks/usePayment';
import {
  ActivityIndicator,
  Dimensions,
  Platform,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import {
  primaryBackgroundColor,
  primaryColor,
  primaryColor2,
  primaryColor3,
  secondaryHoverBackgroundColor,
  primaryBackgroundColor2,
} from '../../../theme/default';
import {PaymentInfo, PaymentReceipt, SupportToken} from '../../../types/order';
import {useSolanaOwnerTokenAccountsProvider} from '../../../hooks/useSolana/useSolanaOwnerTokenAccounts';
import {UserToken} from '../../../db/models/userTokenModel';
import {
  calTokenValue,
  formatNumber,
  parseUnits,
  parseValue,
  toShortAddress,
} from '../../../utils';
import {useAccountProvider} from '../../../hooks/useAccountProvider';
import {UpNetworkLogo} from '../UpNetworkLogo';
import {useSolanaTransaction} from '../../../hooks/useSolana/useSolanaTransaction';
import {LAMPORTS_PER_SOL, Transaction} from '@solana/web3.js';
import {useSolanaClientProvider} from '../../../hooks/useSolana/useSolanaClientProvider';
import LoadingModal from '../Common/LoadingModal';
import {useTranslation} from 'react-i18next';
import {PasskeyAuthFailed} from '../../../types/errors';
import {usePasskeyAuth} from '../../../hooks/usePasskeyAuth';
import {useTokenPriceProvider} from '../../../hooks/useTokenPriceProvider';
import {useNavigation} from '@react-navigation/native';
import {NativeStackNavigationProp} from '@react-navigation/native-stack';
import {RootStackParamList} from '../../Nav/routes';
import tw from 'twrnc';
import ArrowDown from '../../../assets/icons/arrow_down.svg';
import {TokenLogo} from '../TokenLogo';
import {useSwitchTokenModalProvider} from '../../../hooks/useSwitchTokenModalProvider';
import {SwitchTokenModal} from '../SolanaWallet/Token/SwitchToken';
import Toast from 'react-native-toast-message';
import BigNumber from 'bignumber.js';

type PaymentcardProp = {
  orderId: string;
  onReceipt: (receipt: PaymentReceipt) => void;
};

const {width} = Dimensions.get('window');

export default function PaymentCard({
  orderId,
  onReceipt,
}: Readonly<PaymentcardProp>) {
  const {
    orderLoading,
    orderInfo,
    getOrderInfoById,
    getPaymentInfo,
    updateOrderPaymentInfo,
  } = usePayment();
  const [paymentInfo, setPaymentInfo] = useState<PaymentInfo>();
  const [currentPaymentToken, setCurrentPaymentToken] =
    useState<SupportToken>();
  const [currentPaymentTokenList, setCurrentPaymentTokenList] = useState<
    SupportToken[]
  >([]);
  const [currentUserToken, setCurrentUserToken] = useState<UserToken>();
  const [currentUserTokenList, setCurrentUserTokenList] = useState<UserToken[]>(
    [],
  );
  const {userInfo} = useAccountProvider();
  const [rawTx, setRawTx] = useState<Transaction>();
  const [rawFee, setRawFee] = useState<string>('');
  const [feeValue, setFeeValue] = useState<string>('');
  const {solanaClient} = useSolanaClientProvider();
  const [paying, setPaying] = useState<boolean>(false);
  const {getTokenPrice, tokenPrices} = useTokenPriceProvider();
  const {passkeyAuth} = usePasskeyAuth();
  const [paymentInfoLoading, setPaymentInfoLoading] = useState<boolean>(true);

  const {t} = useTranslation();
  const {toggleModal} = useSwitchTokenModalProvider();

  const {userTokens, getTokenAccounts} = useSolanaOwnerTokenAccountsProvider();
  const {createTransferSOLTx, createTransferSPLTx, signTx, sendRawTx} =
    useSolanaTransaction();

  const navigation =
    useNavigation<NativeStackNavigationProp<RootStackParamList>>();

  useEffect(() => {
    navigation.setOptions({
      headerTitle: () => (
        <View
          style={{
            justifyContent: 'center',
            alignItems: 'center',
            flexDirection: 'row',
          }}>
          <Text style={{color: primaryColor2, fontSize: 18, fontWeight: '600'}}>
            {t('payTitle')}
          </Text>
          {(orderLoading || paymentInfoLoading) && (
            <ActivityIndicator
              size="small"
              color={primaryColor}
              style={{marginLeft: 6}}></ActivityIndicator>
          )}
        </View>
      ),
    });
  }, [orderLoading, paymentInfoLoading]);

  useEffect(() => {
    getTokenAccounts();
    getOrderInfoById(orderId);
  }, [orderId]);

  useEffect(() => {
    if (currentPaymentToken != undefined) {
      const token = userTokens.find(item =>
        currentPaymentToken!.isNative
          ? item.symbol.toLowerCase() ==
            currentPaymentToken!.symbol.toLowerCase()
          : item.symbol.toLowerCase() ==
              currentPaymentToken!.symbol.toLowerCase() &&
            item.address.toLowerCase() ==
              currentPaymentToken!.address!.toLowerCase(),
      );
      setCurrentUserToken(token);
    }
  }, [userTokens, currentPaymentToken]);

  const handleSelectToken = (value: UserToken) => {
    const selectPaymentToken = currentPaymentTokenList.find(item => {
      return item.symbol.toLowerCase() == value.symbol.toLowerCase();
    });
    setCurrentPaymentToken(selectPaymentToken);
  };

  useEffect(() => {
    if (currentPaymentTokenList.length > 0) {
      const tokens = userTokens.filter(item => {
        const pToken = currentPaymentTokenList.find(pItem => {
          if (pItem.isNative) {
            return pItem.symbol.toLowerCase() == item.symbol.toLowerCase();
          } else {
            return (
              pItem.symbol.toLowerCase() == item.symbol.toLowerCase() &&
              pItem.address?.toLocaleLowerCase() == item.address.toLowerCase()
            );
          }
        });
        return pToken !== undefined;
      });
      setCurrentUserTokenList(tokens);
      navigation.setOptions({
        headerRight: () =>
          currentUserTokenList.length > 0 ? (
            <TouchableOpacity
              onPress={toggleModal}
              style={tw.style(
                `flex flex-row items-center gap-2 bg-[${primaryBackgroundColor2}] p-2 rounded-xl`,
              )}>
              <TokenLogo
                tokenName={currentUserToken!.name}
                logoUri={currentUserToken!.logo}
                size={20}
                borderRadius={20}
                backgroundColor="blue"
                textFontSize={12}></TokenLogo>

              <Text style={tw.style(`text-[${primaryColor2}]`)}>
                {currentUserToken!.symbol}
              </Text>
              <ArrowDown color="#AAA" width={20} height={20} />
            </TouchableOpacity>
          ) : undefined,
      });
    }
  }, [userTokens, currentPaymentTokenList]);

  useEffect(() => {
    if (!orderLoading && orderInfo != undefined) {
      setCurrentPaymentTokenList(orderInfo.supportTokenList);
      setCurrentPaymentToken(orderInfo.supportTokenList[0]);
    }
  }, [orderLoading, orderInfo]);

  useEffect(() => {
    const getCurrentPaymentInfo = async () => {
      setPaymentInfoLoading(true);
      const userToken = userTokens.find(item => {
        item.symbol.toLowerCase() == currentPaymentToken?.symbol.toLowerCase();
      });
      const info = await getPaymentInfo(
        orderId,
        currentPaymentToken!.symbol,
        userToken?.decimals ?? 6,
        currentPaymentToken?.address,
      );
      console.log('payment info', info);
      if (info == null) {
        //
      } else {
        setPaymentInfo(info);
      }
      setPaymentInfoLoading(false);
    };

    if (currentPaymentToken != undefined) {
      getCurrentPaymentInfo();
    }

    const inerval = setInterval(() => {
      if (currentPaymentToken != undefined) {
        console.log('refresh payment info....');
        getCurrentPaymentInfo();
      }
    }, 20 * 1000);

    return () => {
      clearInterval(inerval);
    };
  }, [currentPaymentToken, orderId, userTokens]);

  useEffect(() => {
    const handleFeeValue = async () => {
      if (rawFee == '') {
        setFeeValue('SGD 0');
      } else {
        const solananPrice = tokenPrices.find(
          item => item.symbol.toLowerCase() == 'sol',
        );
        if (solananPrice != undefined) {
          const feeValue = calTokenValue(
            parseValue(rawFee, 9),
            solananPrice.price,
          );
          setFeeValue(feeValue);
        }

        const solPrice = await getTokenPrice('SOL');
        const feeValue = calTokenValue(parseValue(rawFee, 9), solPrice.price);

        setFeeValue(feeValue);
      }
    };
    handleFeeValue();
  }, [rawFee]);

  useEffect(() => {
    const createTx = async () => {
      console.log('create tx....');
      let tx;
      if (currentUserToken?.type == 'native') {
        tx = await createTransferSOLTx(
          userInfo!.solanaAddress,
          orderInfo!.merchantSolanaAddress,
          Number(paymentInfo!.payTokenAmount),
        );
      } else {
        const amount = BigInt(
          parseUnits(paymentInfo!.payTokenAmount, currentUserToken!.decimals),
        );
        tx = await createTransferSPLTx(
          userInfo!.solanaAddress,
          orderInfo!.merchantSolanaAddress,
          currentUserToken!.address,
          amount,
          currentUserToken!.decimals,
        );
      }
      console.log('tx', tx);
      setRawTx(tx);
      const fee = await tx.getEstimatedFee(solanaClient!);
      setRawFee(fee ? fee + '' : '');
    };
    if (
      currentPaymentToken != undefined &&
      currentUserToken != undefined &&
      orderInfo != undefined &&
      paymentInfo != undefined &&
      userInfo != undefined &&
      solanaClient != undefined
    ) {
      if (orderInfo.paymentStatus == 'success') {
        Toast.show({
          type: 'info',
          text1: t('paymentTitle'),
          text2: t('orderPaymentStatusHint'),
          position: Platform.OS === 'android' ? 'top' : 'bottom',
        });
        navigation.pop();
        return;
      }
      createTx();
    }
  }, [
    orderId,
    currentPaymentToken,
    currentUserToken,
    orderInfo,
    paymentInfo,
    userInfo,
    solanaClient,
  ]);

  const isValidBlanace = useCallback(() => {
    if (
      orderInfo !== undefined &&
      currentUserToken !== undefined &&
      paymentInfo !== undefined
    ) {
      if (currentUserToken.type == 'native') {
        const amount =
          Number(paymentInfo!.payTokenAmount) * LAMPORTS_PER_SOL +
          Number(rawFee);
        return BigNumber(currentUserToken.amount ?? '0').isGreaterThanOrEqualTo(
          BigNumber(amount),
        );
      } else {
        const amount = BigNumber(
          parseUnits(paymentInfo!.payTokenAmount, currentUserToken!.decimals),
        );
        const solTokenAccount = userTokens.find(
          item => item.symbol.toLowerCase() == 'SOL',
        );
        if (solTokenAccount == undefined) {
          return false;
        }
        return (
          BigNumber(solTokenAccount.amount ?? '0').isGreaterThanOrEqualTo(
            BigNumber(rawFee),
          ) &&
          BigNumber(currentUserToken.amount ?? '0').isGreaterThanOrEqualTo(
            amount,
          )
        );
      }
    }
  }, [rawFee, currentUserToken, orderInfo, paymentInfo, userTokens]);

  const handlePay = async () => {
    if (rawTx != undefined && !paying && !orderLoading && !paymentInfoLoading) {
      console.log('paying....');
      setPaying(true);
      try {
        if (orderInfo?.secondVerification) {
          await passkeyAuth();
        }
        if (!isValidBlanace()) {
          Toast.show({
            type: 'error',
            text1: t('paymentTitle'),
            text2: t('insufficientBalance'),
            position: Platform.OS == 'android' ? 'top' : 'bottom',
          });
          setPaying(false);
          return;
        }
        const signedTx = await signTx(rawTx);
        console.log('signedTx', signedTx);
        const timestamp = new Date().getTime();
        const txHash = await sendRawTx(signedTx);
        const updateRes = await updateOrderPaymentInfo({
          transactionId: orderId,
          cryptoSymbol: currentPaymentToken!.symbol,

          cryptoAmount: Number(paymentInfo!.payTokenAmount),
          cryptoTxHash: txHash,
          collectWallet: orderInfo!.merchantSolanaAddress,
          paymentStatus: 'success',
          payerWallet: userInfo!.solanaAddress,
        });
        if (updateRes) {
          onReceipt({
            signature: txHash,
            toAddress: orderInfo!.merchantSolanaAddress,
            merchantName: orderInfo!.merchantName,
            tokenSymbol: paymentInfo!.payTokenSymbol,
            fees: rawFee,
            timestamp: timestamp,
            amount: paymentInfo!.payTokenAmount,
          });
        } else {
          //try again
        }
      } catch (error) {
        //toast
        console.log('pay error', error);
        if (error instanceof PasskeyAuthFailed) {
          //
        }

        Toast.show({
          type: 'error',
          text1: t('paymentTitle'),
          text2: t('payFailed'),
          position: Platform.OS == 'android' ? 'top' : 'bottom',
        });
      }
      setPaying(false);
    }
  };

  return (
    <View style={styles.container}>
      <View style={styles.orderValue}>
        <Text style={styles.orderValueText}>
          {paymentInfo == undefined
            ? '--'
            : `${paymentInfo.payTokenAmount} ${paymentInfo.payTokenSymbol}`}
        </Text>
        <Text style={styles.orderValueText2}>
          ≈{' '}
          {orderInfo == undefined
            ? '--'
            : `${orderInfo?.orderValue} ${orderInfo.currency}`}
        </Text>
      </View>
      <View style={styles.orderInfo}>
        <View style={styles.orderInfoItem}>
          <View style={styles.orderInfoTitle}>
            <Text style={styles.orderInfoTitleText}>To</Text>
          </View>
          <View style={styles.orderInfoContext}>
            <Text style={styles.nameText}>
              {orderInfo == undefined ? '--' : orderInfo.merchantName}
            </Text>
            <Text style={styles.addressText}>
              {orderInfo == undefined
                ? '--'
                : toShortAddress(orderInfo.merchantSolanaAddress, 8)}
            </Text>
          </View>
        </View>
        <View style={styles.orderInfoItem2}>
          <View style={styles.orderInfoTitle}>
            <Text style={styles.orderInfoTitleText}>From</Text>
          </View>
          <View style={styles.orderInfoContext}>
            <Text style={styles.nameText}>
              {userInfo == undefined ? '--' : userInfo.displayName}
            </Text>
            <Text style={styles.addressText}>
              {orderInfo == undefined
                ? '--'
                : toShortAddress(userInfo!.solanaAddress, 8)}
            </Text>
          </View>
        </View>
      </View>
      <View style={styles.walletTokenBalance}>
        <Text style={styles.balanceText}>
          {t('balance')}:
          {currentUserToken == undefined
            ? '--'
            : ` ${currentUserToken.uiAmount} ${currentUserToken.symbol}`}
        </Text>
      </View>
      <View style={styles.fees}>
        <View style={styles.feesTitle}>
          <Text style={styles.feesTitleText}>{t('fees')}</Text>
        </View>
        <View style={styles.feeInfo}>
          <Text style={styles.feeInfoText}>
            {rawFee == '--'
              ? rawFee
              : `${
                  rawFee == ''
                    ? '--'
                    : formatNumber(parseValue(rawFee, 9), 2, 6)
                } SOL`}
          </Text>
          <Text style={styles.feeInfoText2}>≈ {feeValue}</Text>
        </View>
      </View>
      <TouchableOpacity style={styles.payButton} onPress={handlePay}>
        <Text style={styles.payButtonText}>{t('payButtonTitle')}</Text>
      </TouchableOpacity>
      <View style={styles.logo}>
        <UpNetworkLogo color={primaryColor}></UpNetworkLogo>
      </View>
      <LoadingModal
        borderColor={primaryBackgroundColor}
        visible={paying}></LoadingModal>

      {currentUserToken && (
        <SwitchTokenModal
          tokenList={userTokens}
          selectToken={currentUserToken!}
          setSelectToken={value => {
            handleSelectToken(value);
          }}
        />
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  loadingContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: primaryBackgroundColor,
  },
  container: {
    flex: 1,
    justifyContent: 'flex-start',
    alignItems: 'center',
    backgroundColor: primaryBackgroundColor,
  },
  orderValue: {
    justifyContent: 'center',
    alignItems: 'center',
    height: 156,
    marginBottom: 12,
  },
  orderValueText: {
    color: primaryColor2,
    fontSize: 30,
    fontWeight: '600',
  },
  orderValueText2: {
    color: primaryColor2,
    fontSize: 22,
    fontWeight: '600',
  },
  orderInfo: {
    width: width - 32,
    justifyContent: 'flex-start',
    alignItems: 'center',
    marginLeft: 16,
    marginRight: 16,
    borderColor: primaryColor,
    borderWidth: 1,
    borderRadius: 16,
  },
  orderInfoItem: {
    width: width - 60,
    height: 70,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    borderBottomColor: primaryColor,
    borderBottomWidth: 1,
  },
  orderInfoItem2: {
    width: width - 60,
    height: 70,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
  },
  orderInfoTitle: {
    justifyContent: 'center',
    alignItems: 'flex-start',
    width: 48,
  },
  orderInfoTitleText: {
    color: primaryColor3,
    fontSize: 15,
  },
  orderInfoContext: {
    flex: 1,
    alignItems: 'flex-end',
    justifyContent: 'center',
  },
  nameText: {
    fontSize: 16,
    color: primaryColor2,
    fontWeight: '600',
  },
  addressText: {
    fontSize: 14,
    color: primaryColor3,
    fontWeight: '500',
  },
  logo: {
    position: 'absolute',
    justifyContent: 'center',
    alignItems: 'center',
    bottom: 48,
    height: 32,
  },
  walletTokenBalance: {
    marginTop: 4,
    paddingRight: 8,
    width: width - 32,
    justifyContent: 'center',
    alignItems: 'flex-end',
    marginBottom: 24,
  },
  balanceText: {
    color: primaryColor3,
    fontSize: 12,
  },
  fees: {
    marginTop: 12,
    width: width - 32,
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginBottom: 48,
  },
  feesTitle: {
    marginLeft: 10,
    width: 48,
    height: 60,
    justifyContent: 'flex-start',
    alignItems: 'flex-start',
  },
  feesTitleText: {
    fontSize: 15,
    color: primaryColor3,
  },
  feeInfo: {
    flex: 1,
    alignItems: 'flex-end',
    justifyContent: 'flex-start',
    height: 60,
    marginRight: 10,
  },
  feeInfoText: {
    fontSize: 15,
    color: primaryColor2,
    fontWeight: '600',
  },
  feeInfoText2: {
    marginTop: 6,
    fontSize: 14,
    color: primaryColor2,
    fontWeight: '600',
  },
  payButton: {
    width: width - 32,
    height: 48,
    borderRadius: 16,
    borderWidth: 1,
    borderColor: primaryColor,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: secondaryHoverBackgroundColor,
  },
  payButtonText: {
    fontSize: 16,
    color: primaryColor2,
    fontWeight: '600',
  },
});
